package editorsvg.editor.documento;

import editorsvg.editor.atributos.AtrEstilo;
import editorsvg.editor.atributos.AtrTransformacion;
import editorsvg.geometria.MiDimension2D;
import editorsvg.propiedades.GrupoPropiedades;
import editorsvg.propiedades.PropiedadTextoMultilinea;
import editorsvg.utilidades.Angulo;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/**
 *
 * @author Jorge Berjano
 */
public abstract class ElementoGrafico extends ElementoSVG {

    private AtrTransformacion transformacion = new AtrTransformacion();
    private AtrEstilo estilo = new AtrEstilo();
    private static GrupoPropiedades propiedadesTransformacion;
    private static GrupoPropiedades propiedadesEstiloGenerico;

    @Override
    protected void poblarPropiedades() {
        super.poblarPropiedades();
        agregarPropiedades(getPropiedadesTransformacion());
        agregarPropiedades(estilo.obtenerPropiedades());
        agregarPropiedades(getPropiedadesEstiloGenerico());
    }

    @Override
    protected void asignarPropietariosPropiedades() {
        super.asignarPropietariosPropiedades();
        getPropiedadesTransformacion().setPropietario(this);
        estilo.obtenerPropiedades().setPropietario(estilo);
        getPropiedadesEstiloGenerico().setPropietario(this);
    }

    public static GrupoPropiedades getPropiedadesEstiloGenerico() {
        if (propiedadesEstiloGenerico == null) {
            propiedadesEstiloGenerico = new GrupoPropiedades("Estilo generico");
            propiedadesEstiloGenerico.agregarPropiedad(new PropiedadTextoMultilinea("estilo", "style"));

        }
        return propiedadesEstiloGenerico;
    }

    public static GrupoPropiedades getPropiedadesTransformacion() {
        if (propiedadesTransformacion == null) {
            propiedadesTransformacion = new GrupoPropiedades("Transformacion");
            propiedadesTransformacion.agregarPropiedad(new PropiedadTextoMultilinea("transformacion", "transform"));
        }

        return propiedadesTransformacion;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        ElementoGrafico clon = (ElementoGrafico) super.clone();
        clon.transformacion = (AtrTransformacion) transformacion.clone();
        clon.estilo = (AtrEstilo) estilo.clone();
        return clon;
    }

    @Override
    public void pintar(Graphics2D graphics, AjustesGraficos ajustes) {
        estilo.establecerAjustes(ajustes);
    }

    public boolean contiene(Point2D posicion) {
        Shape contorno = getContorno();
        return contorno == null ? false : contorno.contains(posicion);
    }

    @Override
    public boolean contiene(Point2D posicion, double tolerancia) {
        Shape contorno = getContorno();
        Rectangle2D rectangulo = new Rectangle2D.Double(
                posicion.getX() - tolerancia / 2,
                posicion.getY() - tolerancia / 2,
                tolerancia, tolerancia);
        return contorno == null ? false : contorno.contains(rectangulo) || contorno.intersects(rectangulo);
    }

    public void transformar(AffineTransform transformacion) {
        this.transformacion.combinar(transformacion);
    }

    public void desplazar(double dx, double dy) {
        transformacion.desplazar(dx, dy);
    }

    public void escalar(Rectangle2D encuadreInicial, Rectangle2D encuadreFinal) {
        transformacion.escalar(encuadreInicial, encuadreFinal);
    }

    public void rotar(Angulo anguloRotacion, double x, double y) {
        transformacion.rotar(anguloRotacion, x, y);
    }

    @Override
    public abstract Shape getContorno();

    @Override
    public Rectangle2D getEncuadre() {
        if (getContorno() == null) {
            return null;
        }
        return getContorno().getBounds2D();
    }

    public Dimension2D getTamaño() {
        if (getEncuadre() == null) {
            return null;
        }
        return new MiDimension2D.Double(getEncuadre().getWidth(), getEncuadre().getHeight());
    }

    public Point2D getCentro() {
        return new Point2D.Double(getEncuadre().getX(), getEncuadre().getY());
    }

    public AtrTransformacion transformacion() {
        return transformacion;
    }

    public AtrEstilo estilo() {
        return estilo;
    }

    public AffineTransform getTransformacion() {
        return transformacion.getValor();
    }
}
